/*
 * Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
 */
package com.origin.floatwindowpermission.permission;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.origin.floatwindowpermission.R;
import com.origin.uilibrary.lihang.ShadowLayout;
import com.origin.utils.screen.ScreenUtils;


/**
 * Description:
 *
 * @author zhaozp
 * @since 2016-05-19
 */
public class InAppFloatView extends RelativeLayout {
    private static final String TAG = "AVCallFloatView";

    /**
     * 记录手指按下时在小悬浮窗的View上的横坐标的值
     */
    private float xInView;

    /**
     * 记录手指按下时在小悬浮窗的View上的纵坐标的值
     */
    private float yInView;
    /**
     * 记录当前手指位置在屏幕上的横坐标值
     */
    private float xInScreen;

    /**
     * 记录当前手指位置在屏幕上的纵坐标值
     */
    private float yInScreen;

    /**
     * 记录手指按下时在屏幕上的横坐标的值
     */
    private float xDownInScreen;

    /**
     * 记录手指按下时在屏幕上的纵坐标的值
     */
    private float yDownInScreen;

    private boolean isAnchoring = false;
    private boolean isShowing = false;
    private WindowManager windowManager = null;
    private int statusBarHeight;
    private int screenWidth;
    private int screenHeight;

    public InAppFloatView(Context context) {
        super(context);
        initView();
    }

    ShadowLayout shadowLayout;

    private void initView() {
        statusBarHeight = ScreenUtils.getStatusBarHeight(this.getContext());
        screenWidth = ScreenUtils.getScreenWidth(this.getContext());
        screenHeight = ScreenUtils.getScreenHeight(this.getContext());
        mRadiusPx = dp2px(mRadiusDip);
        windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        LayoutInflater inflater = LayoutInflater.from(getContext());
        View floatView = inflater.inflate(R.layout.float_window_layout, null);
        shadowLayout = floatView.findViewById(R.id.window_root);
        shadowLayout.setSpecialCorner(mRadiusPx, 0, mRadiusPx, 0);
        addView(floatView);

    }

    private int mDirection = -1;
    private int mRadiusDip = 8;
    private int mRadiusPx;

    /**
     * @param direction 0 左 1 中 2 右
     */
    public void callDirection(int direction) {
        if (mDirection == direction) {
            return;
        }
        mDirection = direction;
        if (mDirection == 0) {
            shadowLayout.setSpecialCorner(0, mRadiusPx, 0, mRadiusPx);
        } else if (mDirection == 1) {
            shadowLayout.setSpecialCorner(mRadiusPx, mRadiusPx, mRadiusPx, mRadiusPx);
        } else {
            shadowLayout.setSpecialCorner(mRadiusPx, 0, mRadiusPx, 0);
        }

    }

    public void setParams(ViewGroup.LayoutParams params) {
        setLayoutParams(params);
    }

    public void setIsShowing(boolean isShowing) {
        this.isShowing = isShowing;
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                xInView = event.getX();
                yInView = event.getY();
                xDownInScreen = event.getRawX();
                yDownInScreen = event.getRawY();
                xInScreen = event.getRawX();
                yInScreen = event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                xInScreen = event.getRawX();
                yInScreen = event.getRawY();
                callDirection(1);
                // 手指移动的时候更新小悬浮窗的位置
                updateViewPosition();
                break;
            case MotionEvent.ACTION_UP:
                if (Math.abs(xDownInScreen - xInScreen) <= ViewConfiguration.get(getContext()).getScaledTouchSlop()
                        && Math.abs(yDownInScreen - yInScreen) <= ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
                    // 点击效果
                    Toast.makeText(getContext(), "this float window is clicked", Toast.LENGTH_SHORT).show();
                } else {
                    //吸附效果
                    anchorToSide();
                }
                break;
            default:
                break;
        }
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isAnchoring) {
            return true;
        }
        return super.onTouchEvent(event);

    }


    private void anchorToSide() {
        float xDistance = 0;
        int animTime = 0;
        int middleX = screenWidth / 2;
        if (getX() < middleX) {
            // 左
            xDistance = getX() * -1;
        } else {
            // 右
            xDistance = screenWidth - getX() - getWidth();
        }
        animTime = (int) (((float) xDistance / (float) screenWidth) * 600f);
        this.post(new AnchorAnimRunnable(Math.abs(animTime), xDistance, getY(), System.currentTimeMillis()));
    }

    public int dp2px(float dp) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }

    private class AnchorAnimRunnable implements Runnable {

        private int animTime;
        private long currentStartTime;
        private Interpolator interpolator;
        private float xDistance;
        private float yDistance;
        private float startX;
        private float startY;

        public AnchorAnimRunnable(int animTime, float xDistance, float yDistance, long currentStartTime) {
            this.animTime = animTime;
            this.currentStartTime = currentStartTime;
            interpolator = new AccelerateDecelerateInterpolator();
            this.xDistance = xDistance;
            this.yDistance = yDistance;
            startX = getX();
            startY = getY();
        }

        @Override
        public void run() {
            if (System.currentTimeMillis() >= currentStartTime + animTime) {
                if (xDistance > 0) {
                    callDirection(2);
                    setX(screenWidth - getWidth());
                } else {
                    callDirection(0);
                    setX(0);
                }
                return;
            }
            float delta = interpolator.getInterpolation((System.currentTimeMillis() - currentStartTime) / (float) animTime);
            int xMoveDistance = (int) (xDistance * delta);
            setX(startX + xMoveDistance);
            InAppFloatView.this.postDelayed(this, 16);
        }
    }

    private void updateViewPosition() {
        int x = (int) (xInScreen - xInView);
        int y = (int) (yInScreen - yInView * 2);
        if (x < 0) {
            x = 0;
        } else if (x + getWidth() > screenWidth) {
            x = screenWidth - getWidth();
        }
        if (y < 0) {
            y = 0;
        } else if (y + getHeight() + statusBarHeight > screenHeight) {
            y = screenHeight - getHeight() - statusBarHeight;
        }
        setX(x);
        setY(y);
    }
}
